package com.example.demo.core.advice;

import com.example.demo.core.annotations.RestPack;
import com.example.demo.core.exception.NotFoundException;
import com.example.demo.core.exception.PermissionException;
import com.example.demo.core.exception.ProgramException;
import com.example.demo.core.exception.SignInException;
import com.example.demo.core.model.StatusEnum;
import com.example.demo.model.Result;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Method;
import java.sql.SQLException;

/**
 * @author yujie
 */
@ControllerAdvice
public class GlobalHandler implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        Method method = methodParameter.getMethod();
        return method != null && method.isAnnotationPresent(RestPack.class);
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        return (o instanceof Result) ? (Result<?>) o : Result.returnGenEriCity(o);
    }


    @ResponseBody
    @ExceptionHandler({RuntimeException.class})
    public Result<Throwable> exceptionHandler(RuntimeException e) {
        return Result.returnError(StatusEnum.PRO_ERROR.getStatus(), e.getMessage(), e.getCause());
    }

    @ResponseBody
    @ExceptionHandler({NullPointerException.class})
    public Result<Throwable> nullPointerExceptionHandler(NullPointerException e) {
        return Result.returnError(StatusEnum.PRO_ERROR.getStatus(), e.getMessage(), e.getCause());
    }

    @ResponseBody
    @ExceptionHandler({SQLException.class})
    public Result<Throwable> sqlExceptionHandler(SQLException e) {
        return Result.returnError(StatusEnum.PRO_ERROR.getStatus(), e.getMessage(), e.getCause());
    }

    @ResponseBody
    @ExceptionHandler({NotFoundException.class})
    public Result<Throwable> notFoundExceptionHandler(NotFoundException e) {
        return Result.returnError(e.getStatus(), e.getMessage(), e.getCause());
    }

    @ResponseBody
    @ExceptionHandler({PermissionException.class})
    public Result<Throwable> permissionExceptionHandler(PermissionException e) {
        return Result.returnError(e.getStatus(), e.getMessage(), e.getCause());
    }

    @ResponseBody
    @ExceptionHandler({SignInException.class})
    public Result<Throwable> signInExceptionHandler(SignInException e) {
        return Result.returnError(e.getStatus(), e.getMessage(), e.getCause());
    }

    @ResponseBody
    @ExceptionHandler({ProgramException.class})
    public Result<Throwable> programExceptionHandler(ProgramException e) {
        return Result.returnError(e.getStatus(), e.getMessage(), e.getCause());
    }

    @ResponseBody
    @ExceptionHandler({Exception.class})
    public Result<Object> exceptionHandler(Exception e) {
        return Result.returnError(StatusEnum.PRO_ERROR.getStatus(), e.getMessage());
    }


}
